package com.cgt.common.utils;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

@Slf4j
@Data
public class CookieBuilder {
    private Charset charset = StandardCharsets.UTF_8;
    private int maxAge = -1;
    private String path = "/";
    private boolean httpOnly;
    private String name;
    private String value;
    private String domain;
    private final HttpServletRequest request;
    private final HttpServletResponse response;

    public CookieBuilder(HttpServletRequest request, HttpServletResponse response) {
        this.request = request;
        this.response = response;
    }

    /**
     * 构建cookie，会对cookie值用UTF-8做URL编码，避免中文乱码
     */
    public void build(){
        if (response == null) {
            log.error("response为null，无法写入cookie");
            return;
        }
        String encodedValue = null;
        try {
            encodedValue = URLEncoder.encode(value, charset.name());
        } catch (UnsupportedEncodingException e) {
            log.error("编码cookie值时发生错误", e);
            encodedValue = value;
        }
        Cookie cookie = new Cookie(name, encodedValue);
        if(StringUtils.isNotBlank(domain)) {
            cookie.setDomain(domain);
        } else if (request != null) {
            String serverName = request.getServerName();
            // 检查是否是IP地址格式，如果是则不设置domain
            if (!isIpAddress(serverName)) {
                serverName = StringUtils.subAfter(serverName, ".", false);
                cookie.setDomain("." + serverName);
            }
            // 如果是IP地址，则不设置domain，使用浏览器默认行为
        }
        cookie.setHttpOnly(httpOnly);
        cookie.setMaxAge(maxAge);
        cookie.setPath(path);
        log.debug("生成cookie，编码方式:{}，【{}={}，domain:{};maxAge={};path={};httpOnly={}】",
                charset.name(), name, value, domain, maxAge, path, httpOnly);
        response.addCookie(cookie);
    }

    // 手动实现链式调用的setter方法
    public CookieBuilder charset(Charset charset) {
        this.charset = charset;
        return this;
    }

    public CookieBuilder maxAge(int maxAge) {
        this.maxAge = maxAge;
        return this;
    }

    public CookieBuilder path(String path) {
        this.path = path;
        return this;
    }

    public CookieBuilder httpOnly(boolean httpOnly) {
        this.httpOnly = httpOnly;
        return this;
    }

    public CookieBuilder name(String name) {
        this.name = name;
        return this;
    }

    public CookieBuilder value(String value) {
        this.value = value;
        return this;
    }

    public CookieBuilder domain(String domain) {
        this.domain = domain;
        return this;
    }

    /**
     * 利用UTF-8对cookie值解码，避免中文乱码问题
     * @param cookieValue cookie原始值
     * @return 解码后的值
     */
    public String decode(String cookieValue){
        try {
            return URLDecoder.decode(cookieValue, charset.name());
        } catch (UnsupportedEncodingException e) {
            log.error("解码cookie值时发生错误", e);
            return cookieValue;
        }
    }

    /**
     * 判断字符串是否为IP地址格式
     * @param str 待判断的字符串
     * @return 是否为IP地址
     */
    private boolean isIpAddress(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        String[] parts = str.split("\\.");
        if (parts.length != 4) {
            return false;
        }
        for (String part : parts) {
            try {
                int num = Integer.parseInt(part);
                if (num < 0 || num > 255) {
                    return false;
                }
            } catch (NumberFormatException e) {
                return false;
            }
        }
        return true;
    }

}
